package com.wuliang.interview.results;

import java.util.*;

/**
 * 现有以下任意格式的数字（int类型）组成的字符串，多组数字之间用应为"," 隔开，区间之间用 “,” 隔开。
 * 1） 单个数字如 1,3,5,8等；
 * 2） 区间如 1-5,10-15等，包含起止数字和中间数字；
 * 3） 区间加数字如1-9900,9999；
 * 现有两个字符串A和B，完成一下三个方法
 * 1） 判断A的数字是否全部在B的数字范围内，返回true或false；
 * 2） 求两个字符串的交集，如 “1-10,20,22” 和 “2-11,20-30” 两个的交集为 "2-10,20,22"；
 * 3） 求两个字符串的合集，如 “1-10,20,22” 和 “2-11,20-30” 两个的合集为 "1-11,20-30"；
 */
public class Second {

    /**
     * 输入字符串的封装
     */
    static class IntegerString {
        /**
         * 输入的字符串
         */
        private final String input;

        /**
         * 对输入字符串拆分后的具体数组
         */
        private final List<Integer> array;

        public IntegerString() {
            this.input = "";
            this.array = new LinkedList<>();
        }

        public IntegerString(List<Integer> array) {
            this.input = "";
            this.array = array;
        }

        public IntegerString(String input) {
            this.input = input;
            this.array = new LinkedList<>();
            initList();
        }

        /**
         * 初始化数组
         */
        public void initList() {
            // 声明提个输入数组
            String[] inputList = null;
            // 如果当前输入的字符串中包含 “,” 则按照 “,” 切分字符串，并赋值给上述输入数组
            if (this.input.contains(",")) {
                inputList = this.input.split(",");
            }
            // 如果输入参数数组为空，则将-转换为全部数组
            if (inputList == null || inputList.length < 1) {
                if (this.input.contains("-")) {
                    parseToString(this.input);
                }
                return;
            }
            // 遍历输入数组 以获取全部数字
            for (String inputOfString : inputList) {
                if (inputOfString.contains("-")) {
                    parseToString(inputOfString);
                } else {
                    this.array.add(Integer.parseInt(inputOfString));
                }
            }
        }

        /**
         * 将输入的缩写格式转换成具体数组，
         *
         * @param inputSpliceOfTo 输入的缩写 例如 1-20
         */
        public void parseToString(String inputSpliceOfTo) {
            // 活去 “-” 所在的索引位置
            int toIndex = inputSpliceOfTo.indexOf("-");
            // 获取字符串中的起止数字
            int startInteger = Integer.parseInt(inputSpliceOfTo.substring(0, toIndex));
            int endInteger = Integer.parseInt(inputSpliceOfTo.substring(toIndex + 1));
            // 遍历赋值
            for (int i = startInteger; i <= endInteger; i++) {
                this.array.add(i);
            }
        }

        /**
         * 将数组缩写
         * @param builder
         */
        public void abbreviationArray(StringBuilder builder) {
            // 声明一个缓存map，用来存放起止数字或者是单个数字
            Map<Integer, Integer> cache = new HashMap<>();
            // 起始数字暂为数组中的第一个数字
            Integer start = array.get(0);
            // 遍历数组
            for (int i = 1; i < array.size(); i++) {
                // 获取当前遍历的数字
                int current = array.get(i);
                // 复制当前索引对象
                int preIndex = Integer.parseInt(i + "");
                // 如果当前遍历的数字与数组中的前一个数字是相连的，则将当前数字作为止数字存进map中。
                if (current - array.get(--preIndex) == 1) {
                    cache.put(start, current);
                } else {
                    // 如果不是相邻的，则作为单个数字存进缓存map中
                    start = current;
                    cache.put(start, null);
                }
            }
            // 遍历map集合，格式化输出
            cache.forEach((key, value) -> {
                if (value != null) {
                    builder.append(key).append("-").append(value).append(",");
                } else {
                    builder.append(key).append(",");
                }
            });
        }

        /**
         * 重写 toString 方法
         * @return 特定格式
         */
        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            array.sort(Comparator.comparingInt(o -> o));
            abbreviationArray(builder);
            String result = builder.toString();
            return result.substring(0, result.length() - 1);
        }
    }

    /**
     * 判断A的数字是否全部在B的数字范围内，返回true或false
     *
     * @param inputOfA 字符串A
     * @param inputOfB 字符串B
     * @return 是否包含
     */
    public static boolean test(String inputOfA, String inputOfB) {
        // 声明输入参数A
        IntegerString integerStringOfA = new IntegerString(inputOfA);
        // 声明输入参数B
        IntegerString integerStringOfB = new IntegerString(inputOfB);
        // 声明缓存集合
        List<Integer> cache = new LinkedList<>();
        // 遍历A B两个数组，以对比相同数字，并存进缓存集合中
        for (Integer inputAByInt : integerStringOfA.array) {
            for (Integer inputBByInt : integerStringOfB.array) {
                if (inputAByInt.equals(inputBByInt)) {
                    cache.add(inputAByInt);
                }
            }
        }
        // 比较缓存集合是否与输入参数A相等
        return cache.equals(integerStringOfA.array);
    }

    /**
     * 求两个字符串的交集，如 “1-10,20,22” 和 “2-11,20-30” 两个的交集为 "2-10,20,22"
     * @param inputOfA A字符串
     * @param inputOfB B字符串
     */
    public static String test1(String inputOfA, String inputOfB) {
        // 声明输入参数A
        IntegerString integerStringOfA = new IntegerString(inputOfA);
        // 声明输入参数B
        IntegerString integerStringOfB = new IntegerString(inputOfB);
        // 声明缓存集合
        List<Integer> cache = new LinkedList<>();
        // 遍历A B两个输入参数，以对比是否两个集合中是否有相同数字，如果有，则存放到缓存集合中
        for (Integer inputAByInt : integerStringOfA.array) {
            for (Integer inputBByInt : integerStringOfB.array) {
                if (inputAByInt.equals(inputBByInt)) {
                    cache.add(inputAByInt);
                }
            }
        }
        // 声明对象并toString
        return new IntegerString(cache).toString();
    }

    /**
     * 求两个字符串的合集，如 “1-10,20,22” 和 “2-11,20-30” 两个的合集为 "1-11,20-30"
     * @param inputOfA A字符串
     * @param inputOfB B字符串
     */
    public static String test2(String inputOfA, String inputOfB) {
        // 声明输入参数A
        IntegerString integerStringOfA = new IntegerString(inputOfA);
        // 声明输入参数B
        IntegerString integerStringOfB = new IntegerString(inputOfB);
        // 声明缓存集合，并将输入参数A格式化后的数组作为初始化数组存放进去
        List<Integer> cache = new LinkedList<>(integerStringOfA.array);
        // 将输入参数B数组存放到缓存集合中
        cache.addAll(integerStringOfB.array);
        // 利用JDK自带的排序，按照我的理解，应该是快排
        cache.sort(Comparator.comparingInt(o -> o));
        return new IntegerString(new ArrayList<>(new HashSet<>(cache))).toString();
    }

    public static void main(String[] args) {
        System.out.println(test2("1-10,20,22", "2-11,23-30"));
        System.out.println(test1("1-10,20,22", "2-11,20-30"));
        System.out.println(test("1,3,5", "1-10"));
    }

}
